import unittest as ut
from ... import DataString as ds
from ..FunctionStatus import *

SECTION_LINE="************************************************************"
SHOW_ENABLE=1
class FunctionStatusTestCase(ut.TestCase):
    def setup(self):
        self._function=CONTROL_FUNCTION_NONE

    def _Parse(self, msg):
        dataStr = ds.CDataString(msg)
        item = CFunctionStatusElement()
        item.SetFunction(self._function)
        item.Parse(dataStr)
        return item

    def _Show(self, item):
        if SHOW_ENABLE:
            print "\n" + SECTION_LINE
            print item.FormDisplayString()

    def _GetSubItem(self, item, subName='', ssubName=''):
        if subName in item._subList:
            subItem = item._subList[subName]

            if ssubName in subItem._subList:
                ssubItem = subItem._subList[ssubName]
                #reutn subItem of the subItem
                return ssubItem
            else:
                #return subItem
                return subItem
        else:
            #no sub item, so return the item that passed in
            return item


    def _GetSubRaw(self, item, name):
        if name in item._subList:
            raw =  item._subList[name]._rawStr
        else:
            raw = ''
        return raw

    def _GetSubInfo(self, item, name):
        if name in item._subList:
            info =  item._subList[name]._infoStr
        else:
            info = ''
        return info

    def _GetSubError(self, item, name):
        if name in item._subList:
            error =  item._subList[name]._errStr
        else:
            error = ''
        return error

    def test_header(self):
        subItemName = "Header"
        item = self._Parse("03030100")

        raw = self._GetSubRaw(item, subItemName)
        info = self._GetSubInfo(item, subItemName)

        self.assertEqual(raw, "0x03")
        self.assertEqual(info, "length:3")

        self._Show(item)

    def test_headerInvalidLen(self):
        subItemName = "Header"
        msgList = ["01030100","02030100","04030100","05030100","06030100","07030100","08030100","09030100"]

        for msg in msgList:
            item = self._Parse(msg)
            raw = self._GetSubRaw(item, subItemName)
            info = self._GetSubInfo(item, subItemName)
            error = self._GetSubError(item, subItemName)
            self.assertNotEqual(raw, "0x03")
            self.assertNotEqual(info, "length:3")
            self.assertEqual(error, "Invalid length")

        #only show the last one, it's enough
        self._Show(item)



class FunctionStatusRdcTestCase(FunctionStatusTestCase):
    def setUp(self):
        self._function=CONTROL_FUNCTION_RDC

    def test_LockFailed(self):
        subItemName = "Function Status"

        item = self._Parse("03820100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x82")
        self.assertEqual(info, "Failed to lock")

        self._Show(item)

    def test_Locked(self):
        subItemName = "Function Status"
        item = self._Parse("03020104")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x02")
        self.assertEqual(info, "Locked")

        self._Show(item)


    def test_Unlocked(self):
        subItemName = "Function Status"
        item = self._Parse("03030100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x03")
        self.assertEqual(info, "UnLocked")

        self._Show(item)

    def test_UnlockedFailed(self):
        subItemName = "Function Status"
        item = self._Parse("03830100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x03")
        self.assertEqual(info, "UnLocked")

        self._Show(item)

    def test_UnlockedFailed(self):
        subItemName = "Function Status"
        item = self._Parse("03830100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x83")
        self.assertEqual(info, "Failed to unlock")

        self._Show(item)

    def _DoorOpen(self, msg, doorName):
        subItemName = "Parameter"

        self.assertEqual(raw, "0x83")
        self.assertEqual(info, "Failed to unlock")

        self._Show(item)

    def _DoorOpen(self, msg, doorName):
        subItemName = "Parameter"
        item = self._Parse(msg)

        sItem = self._GetSubItem(item, subItemName, doorName)
        self.assertNotEqual(item, sItem)

        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "1")
        self.assertEqual(info, "Open")

    def test_DoorOpen(self):
        msgList = {"03830180":"Front Left Door",
                   "03830140":"Front Right Door",
                   "03830120":"Rear Left Door",
                   "03830110":"Rear Right Door",
                   "03830108":"Back Door",
                   "03830104":"Trunk Door"}

        for msg,name in msgList.iteritems():
            self._DoorOpen(msg,name)

    def _DoorClose(self, msg, doorName):
        subItemName = "Parameter"
        item = self._Parse(msg)

        sItem = self._GetSubItem(item, subItemName, doorName)
        self.assertNotEqual(item, sItem)

        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0")
        self.assertEqual(info, "Close")

    def test_DoorClose(self):
        msgList = {"03830100":"Front Left Door",
                   "03830100":"Front Right Door",
                   "03830100":"Rear Left Door",
                   "03830100":"Rear Right Door",
                   "03830100":"Back Door",
                   "03830100":"Trunk Door"}

        for msg,name in msgList.iteritems():
            self._DoorClose(msg,name)


class FunctionStatusSvtTestCase(FunctionStatusTestCase):
    def setUp(self):
        self._function=CONTROL_FUNCTION_SVT

    def test_Started(self):
        subItemName = "Function Status"

        item = self._Parse("03020100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x02")
        self.assertEqual(info, "Started")

        self._Show(item)

    def test_StartedFaield(self):
        subItemName = "Function Status"

        item = self._Parse("03820100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x82")
        self.assertEqual(info, "Failed to start")

        self._Show(item)


    def test_Stopped(self):
        subItemName = "Function Status"

        item = self._Parse("03030100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x03")
        self.assertEqual(info, "Stopped")

        self._Show(item)

    def test_StoppedFailed(self):
        subItemName = "Function Status"

        item = self._Parse("03830100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x83")
        self.assertEqual(info, "Failed to stop")

        self._Show(item)

class FunctionStatusSpdTestCase(FunctionStatusTestCase):
    def setUp(self):
        self._function=CONTROL_FUNCTION_SPD

    def test_Disabled(self):
        subItemName = "Function Status"

        item = self._Parse("03030100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x03")
        self.assertEqual(info, "Cancelled")

        self._Show(item)

    def test_DisabledFailed(self):
        subItemName = "Function Status"

        item = self._Parse("03830100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x83")
        self.assertEqual(info, "Failed to disable")

        self._Show(item)

    def test_InvalidStatus(self):
        subItemName = "Function Status"
        msgList = ["03020100", "03820100"]
        for msg in msgList:
            item = self._Parse(msg)

            sItem = self._GetSubItem(item, subItemName)
            self.assertNotEqual(sItem, item)
            raw = sItem._rawStr
            error = sItem._errStr

            self.assertIn(raw, ["0x02","0x82"])
            self.assertEqual(error, "Invalid Status")

        self._Show(item)

    def test_SpdId(self):
        subItemName = "Parameter"
        msgList = ["03030101", "03830102","03030100"]
        for msg in msgList:
            item = self._Parse(msg)

            sItem = self._GetSubItem(item, subItemName)
            self.assertNotEqual(sItem, item)
            raw = sItem._rawStr
            info = sItem._infoStr

            self.assertIn(raw, ["0x00","0x01","0x02"])
            self.assertRegexpMatches(info, "Id is <[012]>")

        self._Show(item)

    def test_WrongSpdId(self):
        subItemName = "Parameter"
        msgList = ["03030103","03030104", "03830105","03030106"]
        for msg in msgList:
            item = self._Parse(msg)

            sItem = self._GetSubItem(item, subItemName)
            self.assertNotEqual(sItem, item)
            raw = sItem._rawStr
            error = sItem._errStr

            self.assertIn(raw, ["0x03","0x04","0x05","0x06"])
            self.assertRegexpMatches(error, "Invalid id")

        self._Show(item)

class FunctionStatusGeoTestCase(FunctionStatusTestCase):
    def setUp(self):
        self._function=CONTROL_FUNCTION_GEO

    def test_Disabled(self):
        subItemName = "Function Status"

        item = self._Parse("03030100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x03")
        self.assertEqual(info, "Cancelled")

        self._Show(item)

    def test_DisabledFailed(self):
        subItemName = "Function Status"

        item = self._Parse("03830100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x83")
        self.assertEqual(info, "Failed to cancel")

        self._Show(item)

    def test_InvalidStatus(self):
        subItemName = "Function Status"
        msgList = ["03020100", "03820100"]
        for msg in msgList:
            item = self._Parse(msg)

            sItem = self._GetSubItem(item, subItemName)
            self.assertNotEqual(sItem, item)
            raw = sItem._rawStr
            error = sItem._errStr

            self.assertIn(raw, ["0x02","0x82"])
            self.assertEqual(error, "Invalid Status")

        self._Show(item)

    def test_GeoId(self):
        subItemName = "Parameter"
        ssName = "Geo-Fence ID"
        msgList = ["03030101", "03830102","0303010E"]
        for msg in msgList:
            item = self._Parse(msg)

            sItem = self._GetSubItem(item, subItemName, ssName)
            self.assertNotEqual(sItem, item)
            raw = sItem._rawStr
            info = sItem._infoStr

            self.assertIn(raw, ["1","2","14"])

        self._Show(item)

    def test_WrongGeoId(self):
        subItemName = "Parameter"
        msgList = ["0303010F","0383010F"]
        ssName = "Geo-Fence ID"
        for msg in msgList:
            item = self._Parse(msg)

            sItem = self._GetSubItem(item, subItemName, ssName)
            self.assertNotEqual(sItem, item)
            raw = sItem._rawStr
            error = sItem._errStr

            self.assertIn(raw, ["15","20"])
            self.assertRegexpMatches(error, "Invalid ID")

        self._Show(item)


class FunctionStatusMilTestCase(FunctionStatusTestCase):
    def setUp(self):
        self._function=CONTROL_FUNCTION_MIL

    def test_Enabled(self):
        subItemName = "Function Status"

        item = self._Parse("03020100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x02")
        self.assertEqual(info, "Enabled")

        self._Show(item)

    def test_EnableFailed(self):
        subItemName = "Function Status"

        item = self._Parse("03820100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x82")
        self.assertEqual(info, "Failed to enable")

        self._Show(item)

    def test_Disabled(self):
        subItemName = "Function Status"

        item = self._Parse("03030100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x03")
        self.assertEqual(info, "Disabled")

        self._Show(item)

    def test_DisableFailed(self):
        subItemName = "Function Status"

        item = self._Parse("03830100")

        sItem = self._GetSubItem(item, subItemName)
        self.assertNotEqual(sItem, item)
        raw = sItem._rawStr
        info = sItem._infoStr

        self.assertEqual(raw, "0x83")
        self.assertEqual(info, "Failed to disable")

        self._Show(item)








def suite():
    suite = ut.TestSuite()
    #suite.addTest(FunctionStatusTestCase('test_functionStatus'))
    rdcSuite = ut.TestLoader().loadTestsFromTestCase(FunctionStatusRdcTestCase)
    svtSuite = ut.TestLoader().loadTestsFromTestCase(FunctionStatusSvtTestCase)
    spdSuite = ut.TestLoader().loadTestsFromTestCase(FunctionStatusSpdTestCase)
    geoSuite = ut.TestLoader().loadTestsFromTestCase(FunctionStatusGeoTestCase)
    milSuite = ut.TestLoader().loadTestsFromTestCase(FunctionStatusMilTestCase)
    suite.addTest(rdcSuite)
    suite.addTest(svtSuite)
    suite.addTest(spdSuite)
    suite.addTest(geoSuite)
    suite.addTest(milSuite)
    return suite
